4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
11 // You must not remove this notice, or any other, from this software.
16 namespace Microsoft
.JScript
{
19 using System
.Reflection
;
20 using System
.Reflection
.Emit
;
22 internal sealed class Return
: AST
{
23 private Completion completion
;
25 private FunctionScope enclosingFunctionScope
;
26 private bool leavesFinally
;
28 internal Return(Context context
, AST operand
, bool leavesFinally
)
30 this.completion
= new Completion();
31 this.completion
.Return
= true;
32 this.operand
= operand
;
33 ScriptObject scope
= Globals
.ScopeStack
.Peek();
34 while (!(scope
is FunctionScope
)){
35 scope
= scope
.GetParent();
37 this.context
.HandleError(JSError
.BadReturn
);
38 scope
= new FunctionScope(null);
41 this.enclosingFunctionScope
= ((FunctionScope
)scope
);
42 if (this.operand
!= null && this.enclosingFunctionScope
.returnVar
== null)
43 this.enclosingFunctionScope
.AddReturnValueField();
44 this.leavesFinally
= leavesFinally
;
47 internal override Object
Evaluate(){
48 if (this.operand
!= null)
49 this.completion
.value = this.operand
.Evaluate();
50 return this.completion
;
53 internal override bool HasReturn(){
57 internal override AST
PartiallyEvaluate(){
58 if (this.leavesFinally
)
59 this.context
.HandleError(JSError
.BadWayToLeaveFinally
);
60 if (this.operand
!= null){
61 this.operand
= this.operand
.PartiallyEvaluate();
62 if (this.enclosingFunctionScope
.returnVar
!= null)
63 if (this.enclosingFunctionScope
.returnVar
.type
== null){
64 this.enclosingFunctionScope
.returnVar
.SetInferredType(this.operand
.InferType(this.enclosingFunctionScope
.returnVar
), this.operand
);
66 Binding
.AssignmentCompatible(this.enclosingFunctionScope
.returnVar
.type
.ToIReflect(), this.operand
, this.operand
.InferType(null), true);
67 else{ //returning something from a function explicitly typed as Void
68 this.context
.HandleError(JSError
.CannotReturnValueFromVoidFunction
);
71 }else if (this.enclosingFunctionScope
.returnVar
!= null)
72 this.enclosingFunctionScope
.returnVar
.SetInferredType(Typeob
.Object
, null);
76 internal override void TranslateToIL(ILGenerator il
, Type rtype
){
77 //This assumes that rtype == Void.class.
78 this.context
.EmitLineInfo(il
);
79 if (this.operand
!= null)
80 this.operand
.TranslateToIL(il
, this.enclosingFunctionScope
.returnVar
.FieldType
);
81 else if (this.enclosingFunctionScope
.returnVar
!= null){
82 il
.Emit(OpCodes
.Ldsfld
, CompilerGlobals
.undefinedField
);
83 Convert
.Emit(this, il
, Typeob
.Object
, this.enclosingFunctionScope
.returnVar
.FieldType
);
85 if (this.enclosingFunctionScope
.returnVar
!= null)
86 il
.Emit(OpCodes
.Stloc
, (LocalBuilder
)this.enclosingFunctionScope
.returnVar
.GetMetaData());
87 if (this.leavesFinally
){
88 il
.Emit(OpCodes
.Newobj
, CompilerGlobals
.returnOutOfFinallyConstructor
);
89 il
.Emit(OpCodes
.Throw
);
90 }else if (compilerGlobals
.InsideProtectedRegion
)
91 il
.Emit(OpCodes
.Leave
, this.enclosingFunctionScope
.owner
.returnLabel
);
93 il
.Emit(OpCodes
.Br
, this.enclosingFunctionScope
.owner
.returnLabel
);
96 internal override void TranslateToILInitializer(ILGenerator il
){
97 if (this.operand
!= null)
98 this.operand
.TranslateToILInitializer(il
);